<!-- eslint-disable vue/no-v-model-argument -->
<template>
  <div class="config-table-box" v-loading="showLoading">
    <!-- 表格组件 -->
    <el-table
      v-sticky-el-table="{ enable: isVirtualScrollBar, top: 0 }"
      v-bind="$attrs"
      :data="data"
    >
      <!-- 动态生成表格列 -->
      <el-table-column
        v-for="(item, i) in column"
        :key="i"
        :prop="item.key"
        :label="item.title"
        :width="item.width || 'auto'"
        :align="item.align || 'center'"
        :fixed="item.fixed || false"
        :sortable="item.sortable || false"
        :minWidth="item.minWidth"
        :showOverflowTooltip="item.showOverflowTooltip || false"
        :formatter="item.formatter"
      >
        <!-- 表格列头部模板 -->
        <template #header="scope">
          <slotHeader v-if="slotHeader" :row="scope.column" />
          <template v-else>
            <span class="middle">{{scope.column.label}}</span>
            <!-- 显示提示信息 -->
            <el-tooltip v-if="item.tip" :content="item.tip">
              <el-icon class="middle"><WarningFilled /></el-icon>
            </el-tooltip>
          </template>
        </template>
        <!-- 表格列内容模板 -->
        <template v-if="item.dict" #default="props">
          {{setDict(props.row.state, item.dict)}}
        </template>
      </el-table-column>
    </el-table>
     <!-- 分页组件 -->
    <el-pagination
      v-if="isPagination"
      background
      :hide-on-single-page="true"
      v-model:current-page="filter.pageNo"
      v-model:page-size="filter.pageSize"
      :page-sizes="filter.pageSizes"
      layout='total, sizes, prev, pager, next, jumper'
      :total="pageTotal"
      @size-change="query"
      @current-change="query"
      />
  </div>
</template>
<script setup lang="ts">
import { defineProps, PropType, onMounted,  ref, reactive, watch } from 'vue'
import { valueToLabel } from '@/utils/dictionary/index.ts'
import { ElMessage } from 'element-plus'
import { WarningFilled } from '@element-plus/icons-vue'
defineOptions({
  name: 'configTable'
})
const props = defineProps({
  // 表格的数据，需配合 immediately：false使用
  tableData: {
    type: Array as PropType<any[]>,
    default: () => []
  },
  // 是否页面进入后就请求数据
  immediately: {
    type: Boolean,
    default: true
  },
  // 获取接口所需字段
  beforeRequest: {
    type: Function as PropType<() => Record<string, any>>,
    default: () => ({})
  },
  // 获取数据的接口参数
  request: {
    type: Object as PropType<{ path: string, name: string }>,
    default: () => {
      return {}
    }
  },
  // 配置的字段
  column: {
    type: Array as PropType<any[]>,
    required: true
  },
  // 是否需要虚拟滚动条
  isVirtualScrollBar: {
    type: Boolean,
    default: false
  },
  // 是否需要翻页
  isPagination: {
    type: Boolean,
    default: true
  },
  // 分页配置
  pageInfo: {
    type: Object as PropType<{ pageNo: number, pageSize: number }>,
    default: () => {
      return {}
    }
  },
  slotHeader: {
    type: Function
  }
})
const showLoading = ref<boolean>(false) // 加载层
const data = ref<any>([]) // 表格数据
const pageTotal = ref<number>(0) // 总条数
interface PageState {
  pageNo: number,
  pageSize: number,
  pageSizes: number[]
}
// 分页配置
const filter = reactive<PageState>({
  pageNo: 1,
  pageSize: 10,
  pageSizes: [10, 20, 30]
})
// 请求表格数据
const query = async () => {
  try {
    const page = { page: filter.pageNo, size: filter.pageSize, ...props.pageInfo }
    const params = { ...props.beforeRequest(), ...page }
    const modules: Record<string, any> = import.meta.glob('/src/api/*/*.ts', { eager: true })
    if (!modules[props.request.path]) {
      ElMessage.error('查找不到接口')
      return
    }
    showLoading.value = true
    const res = await modules[props.request.path][props.request.name](params)
    data.value = res.data
    pageTotal.value = res.total || 0
  } catch (err) {
    console.error(err)
    ElMessage.error('数据请求失败')
  } finally {
    showLoading.value = false
  }
}
// 刷新表格数据
const refresh = () =>  {
  filter.pageNo = 1
  query ()
}
// 设置字典
interface DictState {
  key: string,
  path: string
}
const setDict = (value:string | number, dict:DictState) => {
  return valueToLabel(value, dict.key, dict.path) || ''
}
// 监听tableData变化
watch(
  () => props.tableData,
  newVal => {
    if (newVal && newVal.length) {
      data.value = newVal
    }
  },
  { immediate: true }
)
// 暴露属性 供父组件使用
defineExpose({ showLoading, query, refresh })
onMounted(() => {
  if (props.immediately) query()
})
</script>
<style lang="scss" scoped>
  .config-table-box{
    .el-pagination{
      margin-top: 20px;
    }
  }
</style>
